package com.general.framework.wukong.blockingQueue.interview;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 定义了一个 ReentrantLock 和与之关联的 Condition（hasTask）。
 * 面试官在每次放入候选人后，减少剩余任务数（remainingTasks），当剩余任务数变为 0 时，通过 hasTask.signalAll() 通知面试者所有任务已安排完。
 * 面试者则通过 hasTask.await(1, TimeUnit.SECONDS) 等待通知，收到通知后，只要队列不为空，就不断从队列中取出候选人进行面试。
 * 如果等待超时（这里设置超时时间为 1 秒，可根据实际情况调整）且没有收到新通知，说明任务已经全部完成，就结束循环，从而避免了往队列中添加特殊标识元素来表示结束。
 */
public class ArrayBlockingQueueDemoByCondition {
    public static void main(String[] args) {
        BlockingQueue<String> queue = new ArrayBlockingQueue<>(3);
        Interviewer2 interviewer = new Interviewer2(queue);
        Interviewee2 interviewee = new Interviewee2(queue);
        new Thread(interviewer).start();
        new Thread(interviewee).start();
    }
}

class Interviewer2 implements Runnable {
    private final BlockingQueue<String> queue;
    private final ReentrantLock lock = new ReentrantLock();
    private final Condition hasTask = lock.newCondition();
    private int remainingTasks = 10;

    public Interviewer2(BlockingQueue<String> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        for (int i = 1; i <= 10; i++) {
            String candidate = "Candidate" + i;
            try {
                queue.put(candidate);
                System.out.println("已安排好了第 " + candidate + " 位候选者");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            lock.lock();
            remainingTasks--;
            if (remainingTasks == 0) {
                hasTask.signalAll();
            }
            lock.unlock();
        }
    }
}

class Interviewee2 implements Runnable {
    private final BlockingQueue<String> queue;
    private final ReentrantLock lock = new ReentrantLock();
    private final Condition hasTask = lock.newCondition();

    public Interviewee2(BlockingQueue<String> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        lock.lock();
        try {
            Thread.sleep(1000);
            hasTask.await(1, TimeUnit.SECONDS);
            while (!queue.isEmpty()) {
                String candidate = queue.take();
                System.out.println("第 " + candidate + " 位候选者面试完毕");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}